using System;
using SMLib.Automata.MM;
using System.Text;
using SMLib.Automata.Base;
using System.Xml;
using System.IO;

namespace SMLib.Interoperability.XML
{
	/// <summary>
	/// XML Import/Export from/to XML files
	/// </summary>
	public class Interop_XML_MM
	{
		/// <summary>
		/// Export the specified Mealy machine 
		/// </summary>
		/// <param name="m">machine</param>
		/// <param name="path">path</param>
		public static void Export (MealyMachine m, string path)
		{
			StringBuilder sb = new StringBuilder ();
			sb.Append ("<mealy-machine>\n");
			//* alphabet
			sb.Append ("<alphabet>\n");
			sb.Append ("<inputs>\n");
			foreach (ISymbol st in m.InputAlphabet.AllSymbols()) {
				sb.Append ("<symbol name=\"" + st.ToString() + "\"/>\n");
			}
			sb.Append ("</inputs>\n");
			sb.Append ("<outputs>\n");
			sb.Append ("</outputs>\n");
			sb.Append ("</alphabet>\n");

			//* locations
			sb.Append ("<locations>\n");
			foreach (MealyMachine.Mealy_State st in m.GetAllStates()) {
				sb.Append ("<location name=\"" + st.ToString() + "\"/>\n");
			}
			sb.Append ("</locations>\n");

			//* transitions
			sb.Append ("<transitions>\n");
			foreach (MealyMachine.Mealy_State st in m.GetAllStates()) {
				foreach (MealyMachine.Mealy_Transition tr in st.Transitions) {
					sb.Append ("<transition from=\"" + st.ToString () + "\" to=\"" + tr.Destination.ToString () + "\" symbol=\"" + tr.ToString () + "\"/>\n");
				}
			}
			sb.Append ("</transitions>\n");
			sb.Append ("</mealy-machine>");
			System.IO.File.WriteAllText (path, sb.ToString ());
		}

		/// <summary>
		/// Import MM from a specified path.
		/// </summary>
		/// <param name="path">Path.</param>
		public static MealyMachine Import (string path)
		{
			MealyMachine m = new MealyMachine();
			m.InputAlphabet = new Alphabet();
			m.OutputAlphabet = new Alphabet();

			String xmlString = System.IO.File.ReadAllText (path);
			using (XmlReader reader = XmlReader.Create(new StringReader(xmlString)))
			{
				while (reader.ReadToFollowing("transition")) {
					//reader.MoveToFirstAttribute ();

					string genre = reader.GetAttribute ("from");
					Console.Write ("From " + genre);
					MealyMachine.Mealy_State src = null;
					foreach (MealyMachine.Mealy_State st in m.GetAllStates()) {
						if (st.ToString () == genre) {
							src = st;
							break;
						}
					}
					if (src == null) {
						src = new MealyMachine.Mealy_State (genre);
						m.AddState (src);
					}

					//reader.MoveToNextAttribute ();
					genre = reader.GetAttribute ("to");
					Console.Write (" to " + genre);
					MealyMachine.Mealy_State dst = null;
					foreach (MealyMachine.Mealy_State st in m.GetAllStates()) {
						if (st.ToString () == genre) {
							dst = st;
							break;
						}
					}
					if (dst == null) {
						dst = new MealyMachine.Mealy_State (genre);
						m.AddState (dst);
					}

					//reader.MoveToNextAttribute ();
					genre = reader.GetAttribute ("symbol");
					Console.WriteLine (" label " + genre);
					StringSymbol i = new StringSymbol (genre.Split ('/') [0]);
					if (!m.InputAlphabet.Contains ((i)))
						m.InputAlphabet.AddSymbol ((i));

					StringSymbol o = new StringSymbol (genre.Split ('/') [1]);
					src.AddTransition(dst,new PairOfSymbols(i,o));
				}
			}
			return m;
		}
	}
}

